1. 资源层面
- Linux 调优(单机 1000 w 连接典型参数)
ulimit -n 1048576 # 进程 fd 上限 echo "* soft nofile 1048576" >> /etc/security/limits.conf net.ipv4.ip_local_port_range = 1024 65535 net.ipv4.tcp_tw_reuse = 1 net.core.somaxconn = 32768 net.netfilter.nf_conntrack_max = 2000000 - 多网卡 + SO_REUSEPORT
8 个监听端口绑定同一端口,内核级负载均衡
2. Netty 代码层面
① 主从 Reactor
java
EventLoopGroup boss = new NioEventLoopGroup(1); // 只负责 accept
EventLoopGroup worker = new NioEventLoopGroup(0); // 0=CPU*2 负责 I/O
ServerBootstrap b = new ServerBootstrap()
.group(boss, worker)
.channel(NioServerSocketChannel.class)
.childOption(ChannelOption.TCP_NODELAY, true)
.childOption(ChannelOption.SO_KEEPALIVE, true)
.childOption(ChannelOption.WRITE_BUFFER_WATER_MARK,
new WriteBufferWaterMark(32 * 1024, 128 * 1024)); // 防止内存暴涨② 心跳 + 空闲检测
java
pipeline.addLast(new IdleStateHandler(25, 0, 0, TimeUnit.SECONDS));
// 服务端 25 秒没收到 ping 就触发 userEventTrigger③ 对象池化
java
msg = RECYCLER.get(); // 使用 Recycler 减少 GC
buf = PooledByteBufAllocator.DEFAULT.directBuffer(); // 堆外内存池④ 无锁化设计
- 一个 Channel 始终绑定同一个 EventLoop,所有操作单线程串行执行,避免锁
- 千万连接 ≠ 千万线程,连接数与线程数解耦
3. 架构层面
- 集群化:LVS/DPVS → 多台 Netty 网关 → Redis 存储会话
- 心跳合并:每 30 秒一次批量 ping,减少空包流量
- 灰度断开:利用
channel.attr()打标,按版本逐步释放,避免瞬时重连风暴
4. 实测数据
阿里云 ecs.ebmg5(96 vCPU 384 G)
- 单实例 1200 w 长连接,内存占用约 240 G(每条连接 ≈ 20 KB)
- QPS 心跳 40 w/s,CPU 65 %,P99 延迟 2 ms
背诵金句
“秒传靠 hash 秒检,断点靠 分片+BitSet;
千万长连接靠 Linux 调优 + 主从 Reactor + 无锁单线程 + 心跳池化。”